
var ModalBox = new Class({
    Implements: [Options, Events],
    options: {
        boxTitle: "baseBoxTitle",
        warpClass: "baseBox",
        boxBodyOuter: "",
        boxBody: "",
        shadowClass: "farShadow",
        closeClass: "baseBoxClose",
        outerClose: false,
        scroll: "hidden",
        movable: true,
        centered: true,
        offsets: {x: 0, y: 0},
        autoHeight: false,
        transforms: {
            computed: ['transformProperty', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform'],
            raw: ['transform', '-webkit-transform', '-moz-transform', '-o-transform', 'msTransform']
        },
        modal: {
            enabled: true,
            background: "#fff",
            zIndex: 100000,
            opacity: 0.7,
            custevents: function() {}
        }
    },
    initialize: function(options) {
        this.setOptions(options);

        this.detectTransforms();

        this.element = this.options.element || $(document.body);
    },
    detectTransforms: function() {
        var testEl = new Element('div'), self = this;

        this.scaleTransform = this.options.transforms.computed.some(function(el, index) {
            var test = el in testEl.style;
            if(test) {
                self.prop = self.options.transforms.raw[index];
            }
            return test;
        });

        if(!this.prop) {
            this.prop = "opacity";
        }
    },
    doBox: function(title, what) {
        var self = this, coords;

        if(!this.options.height || this.options.autoHeight) {
            this.options.autoHeight = true;
        }

        this.getHeight(title, what);

        if(this.options.centered) {
            coords = this.centerBox(this.options.width, this.options.height);

            if(typeOf(coords.x) == "number") {
                coords.x += this.options.offsets.x;
            }
            else {
                coords.x = this.options.offsets.x;
            }

            if(typeOf(coords.y) == "number") {
                coords.y += this.options.offsets.y;
            }
            else {
                coords.y = this.options.offsets.y;
            }

        }
        else {
            coords = this.options.offsets;
        }

        var safeTitle = this.options.id || "popup" + this.element.uid;
        if(document.id(safeTitle)) {
            document.id(safeTitle).retrieve("instance").closeBox();
            return;
        }

        if(this.options.modal.enabled) {
            this.overlay();
        }

        this.wrap = new Element('div#' + safeTitle + '.' + [this.options.shadowClass, this.options.warpClass].join('.'), {
            styles: {
                position    : 'absolute',
                width       : this.options.width,
                height      : this.options.height,
                zIndex      : this.options.modal.zIndex + 1,
                marginLeft  : coords.x,
                marginTop   : coords.y,
                opacity     : 0,
                display     : 'none'
            },
            events: {
                'click:relay(.closeThis)': this.closeBox.bind(this),
                'click': function() {
                    this.wrap.setStyles({
                        zIndex: this.options.modal.zIndex + 1,
                        opacity: 1
                    });
                }.bind(this)
            }
        });

        this.box = new Element('div.' + this.options.boxBodyOuter + '[style=height:' + this.options.height + 'px;]').inject(this.wrap);
        this.body = new Element('div.' + this.options.boxBody).inject(this.box);
        this.title = new Element('div.' + this.options.boxTitle + '[style=z-index:' + (this.options.modal.zIndex + 2) + ';]').inject(this.box, 'top');

        this.setTitle(title);

        this.setHTML(what);

        if(this.options.outerClose === false) {
            new Element('div.boxRight.closeThis.cur.' + this.options.closeClass, {
                html: "<img src='../webstat/img/close.png' />"
            }).inject(this.wrap, 'top');
        }
        else {
            var cwrap = new Element('div.boxRight.closeThis.cur.' + this.options.closeClass + '.' + this.options.shadowClass, {
                styles: {
                    marginTop: -16,
                    marginRight: -14,
                    width: 22,
                    height: 22,
                    "-moz-border-radius": "14px",
                    "border-radius": "14px",
                    border: "2px solid #fff"
                },
                events: {
                    'mouseenter': function() {
                        this.setStyle(self.prop, "scale(1)");
                    },
                    'mouseleave': function() {
                        this.setStyle(self.prop, "scale(.9)");
                    }
                }

            }).inject(this.wrap, 'top').setStyle(self.prop, "scale(.9)");

            new Element('div.boxRight.closeThis.cur.' + this.options.closeClass, {
                styles: {
                    width: 22,
                    height: 22,
                    margin: 0,
                    "text-align": "center",
                    "-moz-border-radius": "14px",
                    "border-radius": "14px",
                    "background-image": "-moz-linear-gradient(34deg, #400,#a00)",
                    "-moz-box-shadow": "inset 2px 2px 5px #000"
                },
                html: "<img src='../webstat/img/close2.png'/>"
            }).inject(cwrap);
        }

        this.wrap.inject(this.element, "top");

        if(this.options.movable) {
            this.wrap.makeDraggable({
                modifiers: {
                    x: "marginLeft",
                    y: "marginTop"
                },
                handle: this.title,
                onStart: function() {
                    this.element.setStyles({
                        'opacity': 0.6,
                        'cursor': 'move'
                    });
                    self.fireEvent("moving", this.element);
                },
                onComplete: function() {
                    this.element.setStyles({
                        'opacity': 1.0,
                        'cursor': 'pointer'
                    });
                    self.fireEvent("moved", this.element);
                }
            });
        }

        this.wrap.setStyle('display', 'block');

        this.body.setStyles({
            "overflow-y": this.options.scroll,
            "overflow-x": "hidden"
        });

        this.showBox();

        this.wrap.store('instance', this);
    },
    getHeight: function(title, what) {
        var height = this.options.height || 0;
        if(this.options.autoHeight) {
            var testerTitle = new Element('div.' + this.options.boxTitle + '[style=width:' + this.options.width + 'px;visibility:hidden;]',{
                html: title
            }).inject(document.body);

            var div = new Element('div.' + this.options.boxBody)
            if(typeOf(what) == 'element') {
                div.adopt(what);
            }
            else {
                div.set('html', what);
            }
            var tester = new Element('div.' + this.options.warpClass + '[style=width:' + this.options.width + 'px;visibility:hidden;]').adopt(div).inject(document.body);

            height = tester.getSize().y + testerTitle.getSize().y;

            tester.destroy();
            testerTitle.destroy();
        }

        this.options.height = height;
    },
    resizeBox: function(newWidth, newHeight, complete) {
        var self = this, titleHeight = this.title.getSize().y;

        var coords = (this.options.centered) ? this.centerBox(newWidth, newHeight + titleHeight) : this.options.offsets;

        var oldDuration = this.wrap.get("morph").options.duration;

        this.wrap.set("morph", {
            duration: 200,
            onStart: function() {
                self.body.setStyle("display", "none");
            },
            onComplete: function() {
                self.setOptions({
                    width: newWidth,
                    height: newHeight + titleHeight
                });

                self.body.setStyles({
                    "height": newHeight,
                    "display": "block"
                });

                if(typeOf(complete) == "function") {
                    complete.apply(this);
                }

                this.removeEvents("complete").setOptions({
                    duration: oldDuration
                });
                self.fireEvent("resize");
            }
        }).morph({
            width: coords.width,
            height: coords.height,
            marginLeft: coords.x,
            marginTop: coords.y
        });
    },
    setHTML: function(what) {
        this.wrap.setStyle('height', this.options.height);

        if(typeOf(what) == 'element') {
            this.body.adopt(what);
        }
        else {
            this.body.set('html', what);
        }
        this.fireEvent("contentLoaded");
    },
    setTitle: function(title) {
        this.title.set('html', title);
    },
    showBox: function() {
        var self = this, obj = {
            opacity: [0, 1]
            };

        if(this.scaleTransform) {
            obj[self.prop] = ["scale(0)", "scale(1)"];
        }

        this.wrap.set("morph", {
            onComplete: function() {
                this.removeEvents("complete");
                self.fireEvent('open');
            }
        }).morph(obj);

    },
    closeBox: function(evt) {
        evt.stop();

        var self = this, obj = {
            opacity: [1, 0]
        };

        if(this.scaleTransform) {
            obj[self.prop] = ["scale(1)", "scale(0)"];
        }

        this.wrap.set("morph", {
            onComplete: function() {
                this.element.destroy();
                self.fireEvent("close");
                if(self.options.modal.enabled && self.modal) {
                    self.overlay();
                }
            }
        }).morph(obj);
    },
    centerBox: function(width, height) {
        var winSize = this.element.getSize();
        var winScroll = this.element.getScroll();
        var windowHeight = this.element.getScrollHeight() - 1;

        var coords = {
            y: winScroll.y + (winSize.y / 2) - (height / 2),
            x: winSize.x / 2 - width / 2,
            width: width,
            height: height
        };

        if(coords.y + height + 20 > windowHeight) {
            coords.y = windowHeight - 20 - height;
        }

        if(coords.y <= 0) {
            coords.y = 20;
        }

        return coords;
    },
    overlay: function() {
        // delete modal
        if(this.modal) {
            this.modal.fade('out');
            this.modal.destroy();
            delete this.modal;
            return false;
        }

        this.modal = new Element('div#modal', {
            styles: {
                position: 'absolute',
                top: 0,
                left: 0,
                width: '100%',
                height: window.getScrollHeight(),
                background: this.options.modal.background,
                zIndex: this.options.modal.zIndex
            },
            events: this.options.modal.custevents
        }).inject(this.element);

        this.modal.fade(this.options.modal.opacity);

        this.modal.addEvent('click', this.closeBox.bind(this));

        return this.modal.store('instance', this);
    }
});
